package site.wetsion.galio.sdk.autoconfigure;

import org.springframework.beans.factory.annotation.Value;
import org.springframework.boot.autoconfigure.condition.ConditionalOnBean;
import org.springframework.boot.context.properties.EnableConfigurationProperties;
import org.springframework.boot.web.servlet.FilterRegistrationBean;
import org.springframework.boot.web.servlet.ServletComponentScan;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.Scope;
import org.springframework.context.annotation.ScopedProxyMode;
import site.wetsion.galio.sdk.common.*;
import site.wetsion.galio.sdk.filter.GalioGlobalFilter;
import site.wetsion.galio.sdk.filter.resource.GalioDefaultUrlFilter;
import site.wetsion.galio.sdk.utils.AccessTokenHolderWrapper;
import site.wetsion.galio.sdk.utils.AuthorizationCodeProvider;
import site.wetsion.galio.sdk.utils.ResourceUtil;
import site.wetsion.galio.sdk.utils.UserAuthUtil;

import java.util.Map;
import java.util.Objects;

/**
 * 自动配置类，自动配置注册了全局的RmsGlobalFilter,默认的URL拦截过滤器
 *
 * @author wetsion
 * @version 1.0
 * @CLassName GalioOauthAutoConfiguration
 * @date 2019/3/8 3:20 PM
 */
@Configuration
@ServletComponentScan("site.wetsion.galio.sdk")
@EnableConfigurationProperties({GalioClientDetailsProperties.class})
public class GalioOauthAutoConfiguration {

    @Bean
    @Scope(value = "request", proxyMode = ScopedProxyMode.INTERFACES)
    public AccessTokenRequest rmsAccessTokenRequest(
            @Value("#{request.parameterMap}") Map<String, String[]> parameters,
            @Value("#{request.getHeader('x-access-token')}") String accessToken,
            @Value("#{request.getAttribute('currentUri')}") String currentUri,
            AccessTokenHolderWrapper accessTokenHolderWrapper) {
        GalioAccessTokenRequest galioAccessTokenRequest = new GalioAccessTokenRequest(parameters);
        galioAccessTokenRequest.setCurrentUri(currentUri);
        GalioOauthAccessToken token = accessTokenHolderWrapper.get(accessToken);
        if (Objects.nonNull(token)) {
            accessTokenHolderWrapper.saveUser(token, accessTokenHolderWrapper.getTokenUser(token.getAccessToken()));
        }
        galioAccessTokenRequest.setExistingToken(token);
        return galioAccessTokenRequest;
    }

    @Bean
    @Scope(value = "session", proxyMode = ScopedProxyMode.INTERFACES)
    public OauthClientContext rmsOauthClientContext(AccessTokenRequest rmsAccessTokenRequest) {
        GalioOauthClientContext context = new GalioOauthClientContext(rmsAccessTokenRequest);
        context.setAccessToken(rmsAccessTokenRequest.getExistingToken());
        return context;
    }

    @Bean
    public GalioGlobalFilter galioGlobalFilter() {
        return new GalioGlobalFilter();
    }

    @Bean
    public ResourceUtil resourceUtil(GalioClientDetailsProperties galioClientDetailsProperties) {
        return new ResourceUtil(galioClientDetailsProperties);
    }

    @Bean
    public UserAuthUtil userAuthUtil(GalioClientDetailsProperties galioClientDetailsProperties) {
        return new UserAuthUtil(galioClientDetailsProperties);
    }

    @Bean
    public GalioDefaultUrlFilter galioDefaultUrlFilter(
            GalioClientDetailsProperties galioClientDetailsProperties,
            ResourceUtil resourceUtil) {
        return new GalioDefaultUrlFilter(galioClientDetailsProperties, resourceUtil);
    }

    @ConditionalOnBean(GalioGlobalFilter.class)
    @Bean
    public FilterRegistrationBean buildGalioGlobalFilter(GalioGlobalFilter galioGlobalFilter) {
        FilterRegistrationBean buildRmsGlobalFilter
                = new FilterRegistrationBean();
        buildRmsGlobalFilter.setFilter(galioGlobalFilter);
        buildRmsGlobalFilter.setOrder(1);
        buildRmsGlobalFilter.addUrlPatterns("/*");
        return buildRmsGlobalFilter;
    }

    @ConditionalOnBean(GalioDefaultUrlFilter.class)
    @Bean
    public FilterRegistrationBean buildGalioUrlFilter(GalioDefaultUrlFilter galioDefaultUrlFilter) {
        FilterRegistrationBean buildRmsUrlFilter
                = new FilterRegistrationBean();
        buildRmsUrlFilter.setFilter(galioDefaultUrlFilter);
        buildRmsUrlFilter.setOrder(3);
        buildRmsUrlFilter.addUrlPatterns("/*");
        return buildRmsUrlFilter;
    }

    @Bean
    public AccessTokenHolderWrapper accessTokenHolderWrapper(ResourceUtil resourceUtil) {
        return new AccessTokenHolderWrapper(resourceUtil);
    }

    @Bean
    public AuthorizationCodeProvider authorizationCodeProvider(
            AccessTokenHolderWrapper accessTokenHolderWrapper,
            GalioClientDetailsProperties galioClientDetailsProperties) {
        return new AuthorizationCodeProvider(galioClientDetailsProperties, accessTokenHolderWrapper);
    }

}
